package com.ebt.m.proposal_v2.dao;

import android.os.Handler;

import com.ebt.m.commons.model.http.CustomTypeApdaterFactory;
import com.ebt.m.proposal_v2.dao.file.DiskUtils;
import com.ebt.m.proposal_v2.dao.file.DownloadAPI;
import com.ebt.m.proposal_v2.dao.file.DownloadProgressInterceptor;
import com.ebt.m.proposal_v2.dao.file.OnDownloadListener;
import com.ebt.m.utils.ConfigData;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.io.File;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Retrofit2.0配置用于文件下载
 *
 * @author archer.qi
 *         Created on 2017/6/1.
 */
public class RetroFileDownloader {
    private static final int TIMEOUT_READ = 20;
    private static final int TIMEOUT_CONNECTION = 10;
    private static RetroFileDownloader mRetroFileDownloader;
    private DownloadAPI api;

    public static RetroFileDownloader getDownloader() {
        if (mRetroFileDownloader == null) {
            synchronized (RetroFileDownloader.class) {
                if (mRetroFileDownloader == null) {
                    mRetroFileDownloader = new RetroFileDownloader();
                }
            }
        }
        return mRetroFileDownloader;
    }

    private RetroFileDownloader() {
        ExecutorService executorService = Executors.newFixedThreadPool(1);
        Gson gson = new GsonBuilder()
                .registerTypeAdapterFactory(new CustomTypeApdaterFactory())
                .create();
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(ConfigData.BASE_URL)
                .client(getOkHttpClient())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create(gson))
                .callbackExecutor(executorService)  //默认CallBack回调在主线程进行,当设置下载大文件时需设置注解@Stream 不加这句话会报android.os.NetworkOnMainThreadException
                .build();
        api = retrofit.create(DownloadAPI.class);
    }

    private OkHttpClient getOkHttpClient() {
        OkHttpClient okHttpClient;
        if (ConfigData.DEBUG) {
            okHttpClient = new OkHttpClient().newBuilder()
                    .readTimeout(TIMEOUT_READ, TimeUnit.SECONDS)
                    .connectTimeout(TIMEOUT_CONNECTION, TimeUnit.SECONDS)
                    .addInterceptor(new DownloadProgressInterceptor())
                    .addInterceptor(new HttpLoggingInterceptor()
                            .setLevel(HttpLoggingInterceptor.Level.BODY))
                    .build();
        } else {
            okHttpClient = new OkHttpClient().newBuilder()
                    .readTimeout(TIMEOUT_READ, TimeUnit.SECONDS)
                    .connectTimeout(TIMEOUT_CONNECTION, TimeUnit.SECONDS)
                    .addInterceptor(new DownloadProgressInterceptor())
                    .build();
        }
        return okHttpClient;
    }

    /**
     * 下载
     *
     * @param url
     * @param callback
     */
    public void download(String url, Callback<ResponseBody> callback) {
        api.downloadFile(url).enqueue(callback);
    }

    public void download(String url, String target, OnDownloadListener listener) {
        Handler UIThreadHandler = new Handler();
        download(url, new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                boolean isSuccessful = response.isSuccessful();
                if (isSuccessful) {
                    File targetFile = DiskUtils.createNewFile(target);
                    if (target != null) {
                        boolean writeOk = DiskUtils.OkioWrite(targetFile, response.body().source());
                        if (writeOk && listener != null) {
                            UIThreadHandler.post(() -> listener.onResponse(url, target));
                            return;
                        }
                    }
                }
                if (listener != null) {
                    File targetFile = new File(target);
                    if (targetFile != null && targetFile.exists()) {
                        targetFile.deleteOnExit();
                    }
                    UIThreadHandler.post(() -> listener.onFailure(-1, "download failure"));
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                t.printStackTrace();
                if (listener != null) {
                    File targetFile = new File(target);
                    if (targetFile != null && targetFile.exists()) {
                        targetFile.deleteOnExit();
                    }
                    UIThreadHandler.post(() -> listener.onFailure(-1, t.getMessage()));
                }
            }
        });
    }

}
